/*
 * tx_start_header_gen.c
 * Created on November 29, 2005; 2:25 PM
 * by vramadurai
 */

/************ System Header Files ***************/
#include <stdio.h>
#include <stdlib.h>

/************ Private Header Files **************/
#include "hs_types.h"
#include "HsTypes.h"
#include "PhyDebug.h"
#include "PhyStruct.h"
#include "PmdGlobals.h"
#include "PhyConstants.h"
#include "tables.h"
#include "tx_functions.h"
#include "wlan_phy_mac.h"

hs_uint32_t length_us;
hs_uint32_t uiLength;

void
init_tx(
            struct HS_PhyTx11bStr  *volatile HS_PhyTx11bPtrTh1
        )
{
    if(HS_PhyTx11bPtrTh1->preamble_type == SHORT_PREAMBLE){
        HS_PhyTx11bPtrTh1->plcp_preamble_bits = PLCP_SHORT_PREAMBLE_BITS;
        HS_PhyTx11bPtrTh1->usSFD = (hs_uint16_t)(SHORT_SFD_PATTERN_TX);
    }
    else{
        HS_PhyTx11bPtrTh1->plcp_preamble_bits = PLCP_PREAMBLE_BITS;
        HS_PhyTx11bPtrTh1->usSFD = (hs_uint16_t)(SFD_PATTERN_TX);
    }

    if(HS_PhyTx11bPtrTh1->preamble_type == SHORT_PREAMBLE){
        HS_PhyTx11bPtrTh1->ucScramState = 0x7f;
        HS_PhyTx11bPtrTh1->ucPrevSymb = 0x02;
    }
    else{
        HS_PhyTx11bPtrTh1->ucScramState = 0x49;
        HS_PhyTx11bPtrTh1->ucPrevSymb = 0x00;
    }

    HS_PhyTx11bPtrTh1->subbuff_toggle = 1;
    HS_PhyTx11bPtrTh1->symbol_count = 0;
}

void
txstart_header_gen(
                        struct HS_PhyTx11bStr  *HS_PhyTx11bPtrTh1,
                        hs_int16_t * restrict asCckDqpskSeq,
                        hs_int16_t * restrict ssDBPSKTbl,
                        ePHYSTATES_TH  *ePhyState,
                        hs_uint8_t *ucStateTable1Bit,
                        hs_uint16_t *usCrc16Table_8bit
                   )
{
    //hs_uint32_t uiLength;
    hs_uint32_t uiLen;
    hs_uint16_t usTemp;
    hs_uint16_t usCRCState;

	init_tx(HS_PhyTx11bPtrTh1);

	/* *************** HEADER GENERATION ****************** */
	HS_PhyTx11bPtrTh1->ucHeaderByte[0] = HS_PhyTx11bPtrTh1->usDateRate;
	HS_PhyTx11bPtrTh1->ucHeaderByte[1] = CCK_CLK_LOCK;
	//printf("HS_PhyTx11bPtrTh1->ucHeaderByte[0]=0x%x\n",HS_PhyTx11bPtrTh1->usDateRate);
	//printf("HS_PhyTx11bPtrTh1->ucHeaderByte[1]=%d\n",CCK_CLK_LOCK);
	/* Modulation type is CCK Hence (HS_PhyTx11bPtrTh1->ucHeaderByte[1] & 0x8) not required */

	uiLength = HS_PhyTx11bPtrTh1->usLength;

	if (HS_PhyTx11bPtrTh1->usDateRate == FIVEDOTFIVE_MBPS)
	{
		/* Len = psdu_len+1 if PBCC. and uiModulation = 1 if PBCC */
		uiLen = uiLength;

		/* uiLen = 2 * psdu_length * 8/11 */
		uiLen = (uiLen<<1)*MUL_FAC_8BY11;
		usTemp = (unsigned short)uiLen;
		uiLen = uiLen >> 16;
		if ( usTemp != 0 )
		{
		  uiLen += 1;
		}/* if */
	}
	else if (HS_PhyTx11bPtrTh1->usDateRate == ELEVEN_MBPS)
	{
		uiLen = uiLength;
		/* uiLen = psdu_length * 8/11 */
		uiLen *= MUL_FAC_8BY11;
		usTemp = (unsigned short)uiLen;
		uiLen = uiLen >> 16;

		if (usTemp != 0)
		{
			uiLen += 1;
			usTemp = ((1<<16) - usTemp);

			if (usTemp >=  MUL_FAC_8BY11)
			{
				HS_PhyTx11bPtrTh1->ucHeaderByte[1] |= 0x80;
			}/* if */
		}/* if */
	}
	else if (HS_PhyTx11bPtrTh1->usDateRate == ONE_MBPS)
	{
		uiLen = uiLength << 3;
	}
	else /* 2Mbps */
	{
		uiLen = uiLength << 2;
	}

    length_us = uiLen;

	HS_PhyTx11bPtrTh1->ucHeaderByte[2] = uiLen & 0xFF;
	HS_PhyTx11bPtrTh1->ucHeaderByte[3] = (uiLen >> 8 ) & 0xFF;

	usCRCState = 0xFFFF;

	uiLen = (HS_PhyTx11bPtrTh1->ucHeaderByte[0] ^ usCRCState) & 0xFF;
	usCRCState >>= 8;
	usCRCState  ^= usCrc16Table_8bit[uiLen];

	uiLen = (HS_PhyTx11bPtrTh1->ucHeaderByte[1] ^ usCRCState) & 0xFF;
	usCRCState >>= 8;
	usCRCState  ^= usCrc16Table_8bit[uiLen];

	uiLen = (HS_PhyTx11bPtrTh1->ucHeaderByte[2] ^ usCRCState) & 0xFF;
	usCRCState >>= 8;
	usCRCState  ^= usCrc16Table_8bit[uiLen];

	uiLen = (HS_PhyTx11bPtrTh1->ucHeaderByte[3] ^ usCRCState) & 0xFF;
	usCRCState >>= 8;
	usCRCState  ^= usCrc16Table_8bit[uiLen];

	usCRCState ^= 0xFFFF;
	HS_PhyTx11bPtrTh1->ucHeaderByte[4] = usCRCState & 0xFF;
	HS_PhyTx11bPtrTh1->ucHeaderByte[5] = ( usCRCState >> 8) & 0xFF;

	/* ************* END HEADER GENERATION **************** */

    *ePhyState = PHY_STATE_TX_SEND_PREAMBLE_TH;
}
